home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d18
/
pibcat.arc
/
PIBCATK.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1989-03-31
|
19KB
|
421 lines
(*----------------------------------------------------------------------*)
(* Display_ZIP_Contents --- Display contents of ZIP file *)
(*----------------------------------------------------------------------*)
PROCEDURE Display_ZIP_Contents( ZIPFileName : AnyStr );
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Display_ZIP_Contents *)
(* *)
(* Purpose: Displays contents of a ZIP file *)
(* *)
(* Calling sequence: *)
(* *)
(* Display_ZIP_Contents( ZIPFileName : AnyStr ); *)
(* *)
(* ZIPFileName --- name of ZIP file whose contents are to be *)
(* listed. *)
(* *)
(* Calls: *)
(* *)
(* Aside from internal subroutines, these routines are required: *)
(* *)
(* Get_Unix_Date --- convert Unix date to string *)
(* Open_File --- open a file *)
(* Close_File --- close a file *)
(* Entry_Matches --- Perform wildcard match *)
(* Display_Page_Titles *)
(* --- Display titles at top of page *)
(* DUPL --- Duplicate a character into a string *)
(* *)
(*----------------------------------------------------------------------*)
(*----------------------------------------------------------------------*)
(* Map of ZIP file entry headers *)
(*----------------------------------------------------------------------*)
CONST
ZIP_Central_Header_Signature = $02014B50;
ZIP_Local_Header_Signature = $04034B50;
ZIP_End_Central_Dir_Signature = $06054B50;
Central_Dir_Found = 5;
TYPE
(* Structure of a local file header *)
ZIP_Local_Header_Type =
RECORD
Signature : LONGINT (* Header signature *);
Version : WORD (* Vers. needed to extract *);
BitFlag : WORD (* General flags *);
CompressionMethod : WORD (* Compression type used *);
FileTime : WORD (* File creation time *);
FileDate : WORD (* File creation date *);
CRC32 : LONGINT (* 32-bit CRC of file *);
CompressedSize : LONGINT (* Compressed size of file *);
UnCompressedSize : LONGINT (* Original size of file *);
FileNameLength : WORD (* Length of file name *);
ExtraFieldLength : WORD (* Length of extra stuff *);
END;
(* Structure of the central *)
(* directory record *)
ZIP_Central_Header_Type =
RECORD
Signature : LONGINT (* Header signature *);
VersionMadeBy : WORD (* System id/program vers. *);
VersionNeeded : WORD (* Vers. needed to extract *);
BitFlag : WORD (* General flags *);
CompressionMethod : WORD (* Compression type used *);
FileTime : WORD (* File creation time *);
FileDate : WORD (* File creation date *);
CRC32 : LONGINT (* 32-bit CRC of file *);
CompressedSize : LONGINT (* Compressed size of file *);
UnCompressedSize : LONGINT (* Original size of file *);
FileNameLength : WORD (* Length of file name *);
ExtraFieldLength : WORD (* Length of extra stuff *);
CommentFieldLength : WORD (* Length of comments *);
DiskStartNumber : WORD (* Disk # file starts on *);
InternalAttributes : WORD (* Text/non-text flags *);
ExternalAttributes : LONGINT (* File system attributes *);
LocalHeaderOffset : LONGINT (* Where local hdr starts *);
END;
VAR
ZIPFile : FILE (* ZIP file to be read *);
ZIP_Entry : ZIP_Central_Header_Type (* Central header *);
ZIP_Pos : LONGINT (* Current byte offset in ZIP file *);
Bytes_Read : INTEGER (* # bytes read from ZIP file file *);
Ierr : INTEGER (* Error flag *);
File_Name : AnyStr (* File name of entry in ZIP file *);
(*----------------------------------------------------------------------*)
(* Get_Next_ZIP_Local_Header --- Get next local header in ZIP file *)
(*----------------------------------------------------------------------*)
FUNCTION Get_Next_ZIP_Local_Header( VAR ZIP_Local_Header :
ZIP_Local_Header_Type;
VAR Error : INTEGER ) : BOOLEAN;
(*----------------------------------------------------------------------*)
(* *)
(* Function: Get_Next_ZIP_Local_Header *)
(* *)
(* Purpose: Gets next local header record in ZIP file *)
(* *)
(* Calling sequence: *)
(* *)
(* OK := Get_Next_ZIP_Local_Header( VAR ZIP_Local_Header: *)
(* ZIP_Local_Header_Type; *)
(* VAR Error : INTEGER ) : *)
(* BOOLEAN; *)
(* *)
(* ZIP_Local_Header --- Local header data *)
(* Error --- Error flag *)
(* OK --- TRUE if header successfully found *)
(* *)
(*----------------------------------------------------------------------*)
BEGIN (* Get_Next_ZIP_Local_Header *)
(* Assume no error to start *)
Error := 0;
(* Position file *)
Seek( ZIPFile , ZIP_Pos );
(* Read in the file header entry. *)
IF ( IOResult <> 0 ) THEN
Error := Format_Error
ELSE
BEGIN
BlockRead( ZIPFile, ZIP_Local_Header, SIZEOF( ZIP_Local_Header ),
Bytes_Read );
(* If wrong size read, or header marker *)
(* byte is incorrect, report ZIP file *)
(* format error. *)
IF ( ( IOResult <> 0 ) OR
( Bytes_Read < SIZEOF( ZIP_Local_Header_Type ) ) ) THEN
Error := Format_Error
ELSE
(* Check for a legitimate header type *)
IF ( ZIP_Local_Header.Signature = ZIP_Local_Header_Signature ) THEN
BEGIN (* Local header -- skip it and associated data *)
ZIP_Pos := ZIP_Pos + ZIP_Local_Header.FileNameLength +
ZIP_Local_Header.ExtraFieldLength +
ZIP_Local_Header.CompressedSize +
SIZEOF( Zip_Local_Header_Type );
END
ELSE IF ( ZIP_Local_Header.Signature = ZIP_Central_Header_Signature ) THEN
BEGIN (* Central header -- we want this *)
Error := Central_Dir_Found;
END
ELSE IF ( ZIP_Local_Header.Signature = ZIP_End_Central_Dir_Signature ) THEN
Error := End_Of_File;
END;
(* Report success/failure to calling *)
(* routine. *)
Get_Next_ZIP_Local_Header := ( Error = 0 );
END (* Get_Next_ZIP_Local_Header *);
(*----------------------------------------------------------------------*)
(* Get_Next_ZIP_Entry --- Get next header entry in ZIP file *)
(*----------------------------------------------------------------------*)
FUNCTION Get_Next_ZIP_Entry( VAR ZIP_Entry : ZIP_Central_Header_Type;
VAR FileName : AnyStr;
VAR Error : INTEGER ) : BOOLEAN;
(*----------------------------------------------------------------------*)
(* *)
(* Function: Get_Next_ZIP_Entry *)
(* *)
(* Purpose: Gets header information for next file in ZIP file *)
(* *)
(* Calling sequence: *)
(* *)
(* OK := Get_Next_ZIP_Entry( VAR ZIP_Entry : *)
(* ZIP_Central_Header_Type; *)
(* VAR FileName : AnyStr; *)
(* VAR Error : INTEGER ) : BOOLEAN; *)
(* *)
(* ZIP_Entry --- Header data for next file in ZIP file *)
(* FileName --- File name for this entry *)
(* Error --- Error flag *)
(* OK --- TRUE if header successfully found, else FALSE *)
(* *)
(*----------------------------------------------------------------------*)
VAR
L : INTEGER;
L_Get : INTEGER;
L_Got : INTEGER;
BEGIN (* Get_Next_ZIP_Entry *)
(* Assume no error to start *)
Error := 0;
(* Position file *)
Seek( ZIPFile , ZIP_Pos );
(* Read in the file header entry. *)
IF ( IOResult <> 0 ) THEN
Error := Format_Error
ELSE
BEGIN
BlockRead( ZIPFile, ZIP_Entry, SIZEOF( ZIP_Central_Header_Type ),
Bytes_Read );
(* If wrong size read, or header marker *)
(* byte is incorrect, report ZIP file *)
(* format error. *)
IF ( IOResult <> 0 ) THEN
Error := Format_Error
ELSE IF ( Bytes_Read < SIZEOF( ZIP_Central_Header_Type ) ) THEN
BEGIN
(* Check for end of directory *)
IF ( ZIP_Entry.Signature = ZIP_End_Central_Dir_Signature ) THEN
Error := End_Of_File
ELSE
Error := Format_Error;
END
ELSE
(* Check for a legitimate header type *)
IF ( ZIP_Entry.Signature = ZIP_Central_Header_Signature ) THEN
BEGIN (* Central header -- we want this *)
(* Pick up file name length. *)
(* Only first 255 chars retrieved. *)
L := ZIP_Entry.FileNameLength;
IF ( L > 255 ) THEN
L_Get := 255
ELSE
L_Get := L;
(* Read file name characters. *)
BlockRead( ZIPFile, FileName[ 1 ], L_Get, L_Got );
(* Check for I/O error *)
IF ( ( IOResult <> 0 ) OR ( L_Get<> L_Got ) ) THEN
Error := Format_Error
ELSE
BEGIN
(* Position to next header *)
ZIP_Pos := ZIP_Pos + ZIP_Entry.ExtraFieldLength +
ZIP_Entry.CommentFieldLength +
ZIP_Entry.FileNameLength +
SIZEOF( Zip_Central_Header_Type );
(* Set length of file name *)
FileName[ 0 ] := CHR( L_Got );
END;
END
(* Check for end of directory *)
ELSE IF ( ZIP_Entry.Signature = ZIP_End_Central_Dir_Signature ) THEN
Error := End_Of_File
(* Anything else is bogus *)
ELSE
Error := Format_Error;
END;
Get_Next_ZIP_Entry := ( Error = 0 );
END (* Get_Next_ZIP_Entry *);
(*----------------------------------------------------------------------*)
(* Find_ZIP_Central_Directory --- Find central ZIP file directory *)
(*----------------------------------------------------------------------*)
FUNCTION Find_ZIP_Central_Directory( VAR Error : INTEGER ) : BOOLEAN;
(*----------------------------------------------------------------------*)
(* *)
(* Function: Find_ZIP_Central_Directory *)
(* *)
(* Purpose: Finds central ZIP file directory *)
(* *)
(* Calling sequence: *)
(* *)
(* OK := Find_ZIP_Central_Directory( VAR Error : INTEGER ) : *)
(* BOOLEAN; *)
(* *)
(* Error --- Error flag *)
(* OK --- TRUE if header successfully found, else FALSE *)
(* *)
(*----------------------------------------------------------------------*)
VAR
ZIP_Local_Hdr : ZIP_Local_Header_Type (* Local header *);
BEGIN (* Find_ZIP_Central_Directory *)
(* Assume no error to start *)
Error := 0;
(* Start at beginning of file. *)
ZIP_Pos := 0;
(* Begin loop over local headers. *)
(* Report success/failure to calling *)
(* routine. *)
WHILE ( Get_Next_ZIP_Local_Header( ZIP_Local_Hdr , Error ) ) DO;
Find_ZIP_Central_Directory := ( Error = Central_Dir_Found );
END (* Find_ZIP_Central_Directory *);
(*----------------------------------------------------------------------*)
(* Display_ZIP_Entry --- Display ZIP file file entry info *)
(*----------------------------------------------------------------------*)
PROCEDURE Display_ZIP_Entry( ZIP_Entry : ZIP_Central_Header_Type ;
File_Name : AnyStr );
VAR
FName : AnyStr;
TimeDate : LONGINT;
TimeDateW : ARRAY[1..2] OF WORD ABSOLUTE TimeDate;
DirS : DirStr;
FExt : ExtStr;
BEGIN (* Display_ZIP_Entry *)
WITH ZIP_Entry DO
BEGIN
(* Pick up short file name. *)
FSplit( File_Name, DirS, FName, FExt );
FName := FName + FExt;
(* See if this file matches the *)
(* entry spec wildcard. Exit if *)
(* not. *)
IF Use_Entry_Spec THEN
IF ( NOT Entry_Matches( FName ) ) THEN
EXIT;
(* Get date and time of creation *)
TimeDateW[ 1 ] := FileTime;
TimeDateW[ 2 ] := FileDate;
(* Display long file name if requested *)
(* and if not the same as the short *)
(* name. *)
IF Show_Long_File_Names THEN
IF ( FName = File_Name ) THEN
File_Name := '';
(* Display this entry's information *)
Display_One_Entry( FName, UnCompressedSize, TimeDate, ZIPFileName,
Current_Subdirectory, File_Name );
END;
END (* Display_ZIP_Entry *);
(*----------------------------------------------------------------------*)
BEGIN (* Display_ZIP_Contents *)
(* Open ZIP file and initialize *)
(* contents display. *)
IF Start_Contents_Listing( ' ZIP file: ',
Current_Subdirectory + ZIPFileName, ZIPFile,
ZIP_Pos, Ierr ) THEN
BEGIN
(* Skip to central directory in ZIP file *)
IF Find_ZIP_Central_Directory( Ierr ) THEN
(* Loop over entries *)
WHILE ( Get_Next_ZIP_Entry( ZIP_Entry , File_Name , Ierr ) ) DO
Display_ZIP_Entry( ZIP_Entry , File_Name )
ELSE
BEGIN
Display_Error( 'Failed to find central ZIP directory' );
Ierr := End_Of_File;
END;
(* Close ZIP file file *)
End_Contents_Listing( ZIPFile , Ierr );
END;
END (* Display_ZIP_Contents *);